// 原型和原型链
//1.所有对象都是通过```new 函数```创建
//2.所有的函数都是对象，函数中可以有属性
//3.所有对象都是引用类型

//原型  prototype
//所有函数都有一个属性：prototype，称之为函数原型
//默认情况下，prototype是一个普通的obj
//默认情况下，prototype中有一个属性constructor，它是一个对象，它指向构造函数本身

//隐形原型 __proto__
//所有的对象都有一个属性：```__proto__```，称之为隐形原型
// var obj = new test()
//  obj.__proto__ === test.prototype
//默认情况下，隐式原型指向创建该对象的函数原型。

function createObject(Con) {
  //1.创建一个新对象obj
  var obj = Object.create(null);
  //2.将obj.__proto__ -> 构造函数原型
  Object.setPrototypeOf(obj, Con.prototype);
  //3.执行构造函数，并接受构造函数返回值
  const ret = Con.apply(obj, [].slice.call(arguments, 1));

  //若构造函数返回值为对象，直接返回对象
  //否则返回obj
  return typeof ret === "object" ? ret : obj;
}

// Without tail recursion optimization
function factorial(n, acc = 1) {
  if (n === 0) {
    return acc;
  } else {
    return factorial(n - 1, n * acc);
  }
}

factorial(1000000);
